package org.nf.web.servlet.param;

import org.nf.web.servlet.MethodArgumentResolver;
import org.nf.web.servlet.ServletApi;

import java.lang.reflect.Parameter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wangl
 * @date 2024/6/17
 */
public class MethodArgumentResolverComposite implements MethodArgumentResolver {

    /**
     * 加载参数解析器
     */
    private final List<MethodArgumentResolver> resolvers = new LinkedList<>();
    /**
     * 参数解析器缓存
     */
    private final Map<Parameter, MethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);

    public void addResolver(MethodArgumentResolver resolver) {
        this.resolvers.add(resolver);
    }

    public void removeResolver(MethodArgumentResolver resolver) {
        this.resolvers.remove(resolver);
    }

    public List<MethodArgumentResolver> getResolvers() {
        return resolvers;
    }

    @Override
    public boolean supports(Parameter parameter) {
        return getArgumentResolver(parameter) != null;
    }

    @Override
    public Object resolve(Parameter parameter, ServletApi servletApi) throws Exception {
        //获取参数解析器
        MethodArgumentResolver resolver = getArgumentResolver(parameter);
        //解析参数
        return resolver.resolve(parameter, servletApi);
    }

    /**
     * 请求参数解析时先从缓存中查找，找不到则从集合中遍历查找，找到后缓存起来便于下次解析，提高解析性能
     */
    private MethodArgumentResolver getArgumentResolver(Parameter parameter) {
        MethodArgumentResolver resolver = argumentResolverCache.get(parameter);
        if (resolver == null) {
            for (MethodArgumentResolver methodArgumentResolver : resolvers) {
                if (methodArgumentResolver.supports(parameter)) {
                    resolver = methodArgumentResolver;
                    argumentResolverCache.put(parameter, resolver);
                    break;
                }
            }
        }
        return resolver;
    }
}
